约瑟夫环问题--递归推导

本文为学习《剑指offer》的记录。因其原理在原作者博客上找不到,所以,只能自己编写记录,如有不当之处,欢迎指正。

题目描述:
n个数,编号为 0 , 1, ……, n-1 排成一个圆圈,从数字 0 开始,每次从这个圆圈中删除第 m 个数,请问最后一个剩下的数是多少?

推导过程
定义一个函数 f(n, m) 为 n 个数中取 m 最后剩下的编号。
第一个被删除的数是 (m-1)%n, 记为 k 。此时因为序列已经不连续,函数可以定义为 f’ ( n-1, m)
明显,最后剩下的编号相等,于是: f(n,m) = f’(n-1, m)

然后我们对剩下的数做一个简单的映射:

k+1 –> 0
k+2 –> 1
.
.
n-1 –> n-k-2
0 –> n-k-1
1 –> n-k
.
.
k-1 –> n-2

这个映射可以记为
p(x) = (x-k-1)%n
其中 x 为映射前的数 (可以自己推导一下)

那么逆映射就是:
p-1(x) = (x + k + 1 ) %n
(还是建议自己推导一下)

那么,对于上面的函数 f’(n-1, m),就有
f’(n-1, m) = p-1[f(n-1, m)] = [f(n-1, m) + k +1]%n = f(n, m)

k= (m-1)%n 代入:
f(n, m) = [f(n-1, m) + m]%n

这就是我们要的通项公式。
很明显,当 n = 1 时,f = 0;
于是:

f(n, m) = 0, n = 1
f(n, m) = [f(n-1, m) + m]%n, n>1

使用循环就可以轻松解决这个问题了。

–END–

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值